{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[45.7, 10.0, 33.6]\n",
      "第0个聚落有32条线\n",
      "45.7 10.0 33.6\n",
      "中间投影,视图编号:0\n",
      "第1个聚落有32条线\n",
      "45.7 33.6 10.0\n",
      "下边投影,视图编号:1\n",
      "第2个聚落有32条线\n",
      "33.6 10.0 45.7\n",
      "右边投影,视图编号:2\n",
      "第3个聚落有32条线\n",
      "45.7 33.6 10.0\n",
      "上边投影,视图编号:3\n",
      "第4个聚落有32条线\n",
      "33.6 10.0 45.7\n",
      "左边投影,视图编号:4\n",
      "xy上下面线段集:64条线\n",
      "xz左右面线段集:64条线\n",
      "yz中间面线段集:32条线\n",
      "收集相关线段结束1:175\n",
      "收集相关线段结束:100\n"
     ]
    }
   ],
   "source": [
    "from collections import defaultdict\n",
    "from 三维投影线段寻找 import get_adjusted_clusters,get_clusters,get_intersect_lines\n",
    "\n",
    "dxf_file_path = 'b.dxf'\n",
    "\n",
    "clusters=get_clusters(dxf_file_path)\n",
    "\n",
    "adjusted_clusters,yz中间面线段集,xy上下面线段集,xz左右面线段集  =get_adjusted_clusters(clusters)\n",
    "intersect_lines=get_intersect_lines(xz左右面线段集,yz中间面线段集,xy上下面线段集)\n",
    "intersect_lines1,intersect_lines2,intersect_lines3 = intersect_lines\n",
    "\n",
    "lines_grouped_by_y = defaultdict(list)\n",
    "lines_grouped_by_x = defaultdict(list)\n",
    "lines_grouped_by_z = defaultdict(list)\n",
    "for line in intersect_lines1:\n",
    "    \n",
    "    y = line[0][1]  # 假设y值是线段第一个点的y坐标\n",
    "    lines_grouped_by_y[y].append(line)\n",
    "for line in intersect_lines2:\n",
    "    \n",
    "    z = line[0][2]  # 假设y值是线段第一个点的y坐标\n",
    "    lines_grouped_by_z[z].append(line)\n",
    "for line in intersect_lines3:\n",
    "    \n",
    "    x = line[0][0]  # 假设y值是线段第一个点的y坐标\n",
    "    lines_grouped_by_x[x].append(line)\n",
    "print(f\"y找到了{len(lines_grouped_by_y )}个面\")\n",
    "print(f\"z找到了{len(lines_grouped_by_z )}个面\")\n",
    "print(f\"x找到了{len(lines_grouped_by_x )}个面\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "ename": "ModuleNotFoundError",
     "evalue": "No module named 'shapely'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mshapely\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mgeometry\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m Polygon\n\u001b[0;32m      2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mtriangle\u001b[39;00m\n\u001b[0;32m      3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mshapely\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mops\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m unary_union\n",
      "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'shapely'"
     ]
    }
   ],
   "source": [
    "from shapely.geometry import Polygon\n",
    "\n",
    "from shapely.ops import unary_union\n",
    "import triangle\n",
    "from stl import mesh\n",
    "import numpy as np\n",
    "\n",
    "import networkx as nx\n",
    "\n",
    "\n",
    "def get_2d_polygon(d,nodes):\n",
    "    if d==0:\n",
    "                        \n",
    "       polygon = Polygon([(y,z) for x,y, z in nodes])\n",
    "    elif d==1:\n",
    "        \n",
    "        polygon = Polygon([(x,z) for x,y, z in  nodes])\n",
    "    else:\n",
    "        \n",
    "       polygon = Polygon([(x,y) for x,y, z in  nodes])\n",
    "    return polygon\n",
    "def get_3dvertices_array(d,t, vertices):\n",
    "    if d==0:\n",
    "                 vertices_array = np.array([(t, y, z) for y, z in vertices])\n",
    "    elif d==1:\n",
    "        vertices_array = np.array([(x, t, z) for x, z in vertices])\n",
    "    else :\n",
    "        vertices_array = np.array([(x, y, t) for x, y in vertices])\n",
    "    return vertices_array\n",
    "\n",
    "def polygon_to_mesh(d,t,polygon):\n",
    "    vertices = list(polygon.exterior.coords)[:-1]\n",
    "            # 创建外环边界的线段列表\n",
    "    segments = [[i, i+1] for i in range(0,len(vertices)-1 )]\n",
    "    segments.append([len(vertices) - 1, 0]) \n",
    "    tridict = {\n",
    "            'vertices': vertices,\n",
    "            'segments': segments,  # 注意：segments 应该是一个列表的列表                   \n",
    "        }\n",
    "    tri = triangle.triangulate(tridict, 'p')\n",
    "    triangles = tri['triangles']\n",
    "    vertices=tri['vertices']\n",
    "   # print(\"  triangles\",  triangles)\n",
    "  #  print(\" vertices2\", vertices)\n",
    "    faces_array = np.array(triangles)  # STL 文件中的索引是从1开始的\n",
    "\n",
    "    vertices_array=get_3dvertices_array(d,t,vertices)\n",
    "        # 创建 mesh 对象\n",
    "    triangle_mesh = mesh.Mesh(np.zeros(faces_array.shape[0], dtype=mesh.Mesh.dtype))\n",
    "    for i, fa in enumerate(faces_array):\n",
    "            for j in range(3):\n",
    "                triangle_mesh.vectors[i][j] = vertices_array[fa[j], :]\n",
    "    return triangle_mesh\n",
    "def merge_meshes(meshes_to_merge):\n",
    "    # 合并所有网格的顶点\n",
    "    combined_data = []\n",
    "    for m in meshes_to_merge:\n",
    "     combined_data.append(m.data)\n",
    "\n",
    "    combined_mesh = mesh.Mesh(np.concatenate(combined_data))\n",
    "    return combined_mesh\n",
    "def get_closed_subgraphs_in_open_faces(d,lines_grouped_by):\n",
    "    meshes_to_merge=[]\n",
    "    for t, items in lines_grouped_by.items():\n",
    "        polygons=[]\n",
    "        G = nx.Graph()\n",
    "        G.add_edges_from(items)\n",
    "\n",
    "        outer_ring=None\n",
    "        inner_rings=[]\n",
    "        if not nx.is_connected(G):\n",
    "            closed_subgraphs_in_current_faces = []\n",
    "            \n",
    "            # 对于不闭合的面，找到所有的连通分量\n",
    "            for component in nx.connected_components(G):\n",
    "            \n",
    "                # 创建一个子图，只包含当前连通分量中的节点和边\n",
    "                subgraph = G.subgraph(component)\n",
    "                # 检查子图是否闭合（形成一个环）\n",
    "                if nx.is_eulerian(subgraph):\n",
    "                    print(f\"当前面闭合图形数{len(closed_subgraphs_in_current_faces)}\")\n",
    "                    eulerian_circuit = list(nx.eulerian_circuit(subgraph))\n",
    "                # 提取顶点列表\n",
    "                    subgraph_nodes = [edge[0] for edge in eulerian_circuit]\n",
    "                    subgraph_polygon = get_2d_polygon(d, subgraph_nodes )\n",
    "\n",
    "                    # 检查是否有环在另一个环内部\n",
    "                    for other_polygon in closed_subgraphs_in_current_faces:\n",
    "                      \n",
    "                        \n",
    "                        if subgraph_polygon.within( other_polygon):\n",
    "                            # 如果内环在外环内，则可以在这里处理（例如，进行三角剖分切割）\n",
    "                            #用shaply对内外环形成的图形内部做三角剖分切割\n",
    "                            print(\"这是一个内环\")\n",
    "                            outer_ring= other_polygon\n",
    "                            inner_rings.append(subgraph_polygon)\n",
    "                            break\n",
    "                        elif other_polygon.within(subgraph_polygon):\n",
    "                         \n",
    "                            print(\"这是一个外环\")\n",
    "                            outer_ring=subgraph_polygon\n",
    "                            inner_rings.append( other_polygon)\n",
    "                            break\n",
    "                        else:\n",
    "                            print(\"分开环\")\n",
    "                           \n",
    "     \n",
    "                    closed_subgraphs_in_current_faces.append(subgraph_polygon )                        \n",
    "          \n",
    "            if outer_ring:\n",
    "                inner_rings_union = unary_union(inner_rings)\n",
    "                poly=outer_ring.difference(inner_rings_union)\n",
    "              #  print(\"poly\",poly)\n",
    "                                # 提取多边形的顶点和边界\n",
    "                vertices = list(poly.exterior.coords)[:-1]\n",
    "                  # 创建外环边界的线段列表\n",
    "                segments = [[i, i+1] for i in range(0,len(vertices)-1 )]\n",
    "                segments.append([len(vertices) - 1, 0])  # 连接最后一个和第一个外环顶点\n",
    "                # 提取所有内环的顶点，并添加到 vertices 列表中\n",
    "                for interior_ring in poly.interiors:\n",
    "                    vertices.extend(list(interior_ring.coords)[:-1])  # 内环顶点，去掉最后一个重复点\n",
    "\n",
    "              \n",
    "\n",
    "                # 创建内环边界的线段列表\n",
    "                for interior_ring in poly.interiors:\n",
    "                    start_index = len(vertices) - len(interior_ring.coords)+1\n",
    "                    for i in range(len(interior_ring.coords) - 2):\n",
    "                        segments.append([start_index + i, start_index + i + 1])\n",
    "                    segments.append([start_index + len(interior_ring.coords) - 2, start_index])  # 连接最后一个和第一个内环顶点\n",
    "\n",
    "                holes = []\n",
    "                for interior_ring in poly.interiors:\n",
    "                    # 可以使用内环的几何中心点作为洞的位置\n",
    "                    holes.append(list(interior_ring.centroid.coords)[0])\n",
    "\n",
    "                # 创建一个三角形库的输入字典\n",
    "                tridict = {\n",
    "                    'vertices': vertices,\n",
    "                    'segments': segments,  # 注意：segments 应该是一个列表的列表\n",
    "                    'holes': holes  # 如果没有内环，则不需要这一项\n",
    "                }\n",
    "               # print(  'vertices', vertices)\n",
    "              #  print( 'segments', segments)\n",
    "              #  print(  'holes', holes)\n",
    "                # 使用 triangle 进行三角划分\n",
    "                tri = triangle.triangulate(tridict, 'p')\n",
    "\n",
    "                                # 假设 tri['triangles'] 包含了三角划分的结果\n",
    "                triangles = tri['triangles']\n",
    "                vertices=tri['vertices']\n",
    "               # print(\"  triangles\",  triangles)\n",
    "               # print(\" vertices2\", vertices)\n",
    "                # 创建一个 numpy 数组来保存顶点和三角形信息\n",
    "              \n",
    "                #draw_3d_p(vertices_array)\n",
    "                faces_array = np.array(triangles)  # STL 文件中的索引是从1开始的\n",
    "        \n",
    "                vertices_array=get_3dvertices_array(d,t,vertices)\n",
    "                # 创建 mesh 对象\n",
    "                triangle_mesh = mesh.Mesh(np.zeros(faces_array.shape[0], dtype=mesh.Mesh.dtype))\n",
    "                for i, fa in enumerate(faces_array):\n",
    "                    for j in range(3):\n",
    "                        triangle_mesh.vectors[i][j] = vertices_array[fa[j], :]\n",
    "\n",
    "                meshes_to_merge.append(triangle_mesh)\n",
    "            else :polygons.extend(closed_subgraphs_in_current_faces)   \n",
    "               \n",
    "        elif nx.is_eulerian(G): \n",
    "           eulerian_circuit = list(nx.eulerian_circuit(G))\n",
    "           subgraph_nodes = [edge[0] for edge in eulerian_circuit]\n",
    "           eulerian_polygon = get_2d_polygon(d, subgraph_nodes )\n",
    "           polygons.append(eulerian_polygon)\n",
    "        else:\n",
    "            print(\"这啥？\")\n",
    "        for polygon in polygons:\n",
    "           triangle_mesh=polygon_to_mesh(d,t,polygon)\n",
    "           meshes_to_merge.append(triangle_mesh)\n",
    "           #我这里也要生成triangle_mesh然后合并起来一起导出\n",
    "    return     meshes_to_merge \n",
    "meshes_to_merge0=get_closed_subgraphs_in_open_faces(0,lines_grouped_by_x)\n",
    "meshes_to_merge1=get_closed_subgraphs_in_open_faces(1,lines_grouped_by_y)\n",
    "meshes_to_merge2=get_closed_subgraphs_in_open_faces(2,lines_grouped_by_z)\n",
    "\n",
    "meshes_to_merge = []\n",
    "\n",
    "# 将其他列表的内容添加到这个列表中\n",
    "meshes_to_merge.extend(meshes_to_merge0)\n",
    "meshes_to_merge.extend(meshes_to_merge1)\n",
    "meshes_to_merge.extend(meshes_to_merge2)\n",
    "\n",
    "# 现在meshes_to_merge包含了所有网格，可以用来合并\n",
    "mesh_merged = merge_meshes(meshes_to_merge)\n",
    "\n",
    "mesh_merged.save('merged_output_mesh.stl')\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
